
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
 */

/*
* CarcasonneMap.java
*
* Created on Feb 16, 2010, 2:20:46 PM
 */
package meeple;

//~--- JDK imports ------------------------------------------------------------

import java.awt.*;
import java.awt.Dimension;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;

import java.io.IOException;

import java.net.*;

import java.sql.Time;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Random;
import java.util.Stack;

import javax.imageio.*;

/**
 *
 * @author rogier
 */
public class CarcasonneMap extends javax.swing.JPanel {
    int                              x_cursor = 0;
    int                              y_cursor = 0;
    Player                           current_player;
    int                              current_player_index;
    Hashtable<String, BufferedImage> images;
    Map                              map;
    Tile                             meeple_tile;
    int                              meeple_x;
    int                              meeple_y;
    ArrayList<Player>                players;

    // Map and Tile Data ,Stack and Hashtable for images
    Random  r;
    boolean setMeeple;
    int     stack_doc_width;
    int     stack_dock_x;
    int     stack_dock_y;

    /** Creates new form CarcasonneMap */

    // Variables to animate a tile over the map
    Tile        tile_cursor;
    TileData    tile_data;
    Stack<Tile> tile_stack;

    // variables to crate top of stack
    Tile         top_stack;
    MapTransform transform;

    public CarcasonneMap() {
        r = new Random();
        initComponents();
        newGame();
        repaint();
    }

    private boolean addTiletoMap() {
        if ((map != null) && (tile_cursor != null)) {
            if (map.setTile(tile_cursor, transform.getMapX(x_cursor), transform.getMapY(y_cursor))) {
                if ((current_player != null) && (current_player.getMeeples() > 0)) {
                    setMeeple   = true;
                    meeple_x    = transform.getMapX(x_cursor);
                    meeple_y    = transform.getMapY(y_cursor);
                    meeple_tile = tile_cursor;
                }

                tile_cursor = null;

                return true;
            } else {
                return false;
            }
        }

        return false;
    }

    private void newGame() {

        // Start new Game
        tile_data  = new TileData();
        tile_stack = tile_data.createStack();
        images     = tile_data.createImages();
        map        = new Map(30, 30);
        map.setRoot(tile_stack.pop());
        transform = new MapTransform(0, 0, 50);
        top_stack = tile_stack.peek();
        players   = new ArrayList<Player>(2);
        players.add(new Player("Rogier", Color.red));
        players.add(new Player("Computer", Color.YELLOW));
        current_player_index = 0;
        current_player       = players.get(current_player_index);
        setMeeple            = false;
    }

    private void nextPlayer() {
        current_player_index += 1;
        current_player_index %= players.size();
        current_player       = players.get(current_player_index);
    }

    @Override
    public void resize(Dimension dmnsn) {
        super.resize(dmnsn);

        // if( transform != null)
        // transform.set_offset(dmnsn.width/2, dmnsn.height/2);
    }

    private void SetTile(Tile tile) {
        tile_cursor = tile;
        repaint();
    }

    /**
     * This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")

    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        setMinimumSize(new java.awt.Dimension(200, 200));
        addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                formMouseClicked(evt);
            }
        });
        addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                formMouseMoved(evt);
            }
        });
        addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                formKeyPressed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);

        this.setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 418,
                Short.MAX_VALUE));
        layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 295,
                Short.MAX_VALUE));
    }                                                               // </editor-fold>//GEN-END:initComponents

    private void formMouseMoved(java.awt.event.MouseEvent evt) {    // GEN-FIRST:event_formMouseMoved

        // TODO add your handling code here:
        if (movementBarEntered(evt)) {
            repaint();
        }

        // System.out.print("Mouse event");
        if (tile_cursor != null) {
            x_cursor = evt.getX();
            y_cursor = evt.getY();
            repaint();
        }
    }                                                                 // GEN-LAST:event_formMouseMoved

    private void formMouseClicked(java.awt.event.MouseEvent evt) {    // GEN-FIRST:event_formMouseClicked

        // TODO add your handling code here:
        if (evt.getButton() == evt.BUTTON1) {
            button1Pressed(evt);
        }

        if (evt.getButton() == evt.BUTTON2) {
            tile_cursor = null;
            nextPlayer();
            repaint();
        }

        if (evt.getButton() == evt.BUTTON3) {
            button3Pressed(evt);
        }
    }                                                             // GEN-LAST:event_formMouseClicked

    private void formKeyPressed(java.awt.event.KeyEvent evt) {    // GEN-FIRST:event_formKeyPressed

        // TODO add your handling code here:
        System.out.print(evt.getKeyChar());

        if (evt.getKeyChar() == 'd') {
            tile_cursor = null;
            repaint();
        }
    }    // GEN-LAST:event_formKeyPressed

    private void button1Pressed(java.awt.event.MouseEvent evt) {
        if (dockPressed(evt)) {
            repaint();

            return;
        }

        if (setMeeple) {
            if (meepleSelected(evt)) {
                setMeeple = false;
                nextPlayer();
                repaint();
            }
        }

        if (addTiletoMap()) {
            repaint();
        }
    }

    private boolean meepleSelected(java.awt.event.MouseEvent evt) {
        int x = evt.getX();
        int y = evt.getY();

        System.out.print("Meeple select");

        for (Position p : Position.values()) {
            if ((x > transform.getScreenX(meeple_x) + p.offsetX())
                    && (x < transform.getScreenX(meeple_x) + p.offsetX() + 8)) {
                if ((y > transform.getScreenY(meeple_y) + p.offsetY())
                        && (y < transform.getScreenY(meeple_y) + p.offsetY() + 8)) {
                    System.out.print(p);
                    meeple_tile.setMeeple(p);
                   // meeple_tile.setOwner(current_player);
                    current_player.removeMeeple();
                    setMeeple = false;

                    return true;
                }
            }
        }

        return false;
    }

    private boolean movementBarEntered(java.awt.event.MouseEvent evt) {

        // System.out.print(evt.toString());
        // System.out.print(this.getSize().toString());
        if (evt.getX() > this.getSize().width - 3) {
            transform.set_offset(transform.getJx_offset() - 5, transform.getJy_offset());

            return true;
        }

        if (evt.getY() > this.getSize().height - 3) {
            transform.set_offset(transform.getJx_offset(), transform.getJy_offset() - 5);

            return true;
        }

        if (evt.getX() < 3) {
            transform.set_offset(transform.getJx_offset() + 5, transform.getJy_offset());

            return true;
        }

        if (evt.getY() < 3) {
            transform.set_offset(transform.getJx_offset(), transform.getJy_offset() + 5);

            return true;
        }

        return false;
    }

    private boolean dockPressed(java.awt.event.MouseEvent evt) {
        if ((evt.getX() > stack_dock_x) && (evt.getX() < stack_dock_x + stack_doc_width) && (evt.getY() > stack_dock_y)
                && (evt.getY() < stack_dock_y + stack_doc_width)) {
            if (tile_cursor == null) {
                SetTile(tile_stack.pop());
                top_stack = tile_stack.peek();
                x_cursor  = evt.getX();
                x_cursor  = evt.getY();

                return true;
            }
        }

        return false;
    }

    private void button3Pressed(java.awt.event.MouseEvent evt) {
        if (tile_cursor != null) {
            tile_cursor.Rotate();
            repaint();
        }

        if (setMeeple) {
            nextPlayer();
            setMeeple = false;
            repaint();
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponents(g);

        Graphics2D g2d = (Graphics2D) g;

        g2d.setColor(Color.BLUE);
        g2d.fillRect(0, 0, this.getSize().width, this.getSize().height);
        drawMap(g2d);

        if (setMeeple) {
            drawMeepleTemplate(g2d, meeple_x, meeple_y);
        }

        drawCursor(g2d);
        drawStackdock(g2d);
        drawPlayerInfo(g2d, current_player);
    }

    private void drawMap(Graphics2D g2d) {
        if ((images != null) && (map != null)) {

            // System.out.print("Images");
            for (int x = 0; x < map.getWidth(); x++) {
                for (int y = 0; y < map.getWidth(); y++) {
                    if (map.hasTile(x, y)) {

                        // g2d.drawImage(images.get(map.getTile(x, y).getName()), transform.getScreenX(x), transform.getScreenY(y), this);
                        drawImage(g2d, images.get(map.getTile(x, y).getName()), map.getTile(x, y).getTurns(),
                                  transform.getScreenX(x), transform.getScreenY(y));

                        if (map.getTile(x, y).getMeeple() != Position.none) {
                            drawMeeple(g2d, map.getTile(x, y).getOwner().getColor(), map.getTile(x, y).getMeeple(),
                                       transform.getScreenX(x), transform.getScreenY(y));
                        }
                    }
                }
            }
        }
    }

    private void drawImage(Graphics2D g2d, int x, int y) {
        g2d.drawImage(images.get(map.getTile(x, y).getName()), transform.getScreenX(x), transform.getScreenY(y), this);
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables

    private void drawCursor(Graphics2D g2d) {
        if ((tile_cursor != null) && (images != null)) {
            System.out.print(transform.getMapX(x_cursor));
            System.out.print(transform.getMapY(y_cursor));
            System.out.print("\n");

            // g2d.drawImage(images.get(tile_cursor.getName()), , transform.getScreenY(transform.getMapY(y_cursor)), this);
            drawImage(g2d, images.get(tile_cursor.getName()), tile_cursor.getTurns(),
                      transform.getScreenX(transform.getMapX(x_cursor)),
                      transform.getScreenY(transform.getMapY(y_cursor)));
        }
    }

    private void drawImage(Graphics2D g2d, BufferedImage image, int rotate, int x, int y) {
        AffineTransform tx = new AffineTransform();

        tx.rotate(Math.toRadians(90 * rotate), image.getWidth() / 2, image.getHeight() / 2);

        AffineTransformOp op  = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
        BufferedImage     tmp = op.filter(image, null);

        g2d.drawImage(tmp, x, y, this);
    }

    private void drawMeeple(Graphics2D g2d, Color c, Position p, int x, int y) {
        x += p.offsetX();
        y += p.offsetY();
        g2d.setColor(c);
        g2d.fillOval(x, y, 8, 8);
    }

    private void drawMeepleTemplate(Graphics2D g2d, int x, int y) {
        for (Position p : Position.values()) {
            if (p != p.none) {
                g2d.setColor(Color.WHITE);
                g2d.drawRect(transform.getScreenX(x) + p.offsetX(), transform.getScreenY(y) + p.offsetY(), 8, 8);
            }
        }
    }

    private void drawStackdock(Graphics2D g2d) {
        stack_doc_width = 60;
        stack_dock_x    = this.getSize().width - stack_doc_width;
        stack_dock_y    = this.getSize().height - stack_doc_width;

        if ((top_stack != null) && (images != null)) {
            Rectangle2D rect = new Rectangle2D.Double(stack_dock_x, stack_dock_y, stack_doc_width, stack_doc_width);

            g2d.setColor(Color.BLACK);
            g2d.draw(rect);
            g2d.drawImage(images.get(top_stack.getName()), stack_dock_x + 5, stack_dock_y + 5, this);
        }
    }

    private void drawPlayerInfo(Graphics2D g2d, Player p) {
        if (p != null) {
            Font font = new Font("Serif", Font.BOLD, 14);

            g2d.setColor(Color.BLACK);
            g2d.setFont(font);

            // Draw a string such that the top-left corner is at x, y
            FontMetrics fontMetrics = g2d.getFontMetrics();

            g2d.drawString("Player:" + p.getName(), 10, 10 + fontMetrics.getAscent());
            g2d.drawString("Meeples: " + p.getMeeples(), 10, 10 + 2 * fontMetrics.getAscent());
            g2d.drawString("Score:" + p.getScore(), 10, 10 + 3 * fontMetrics.getAscent());
        }
    }
}


//~ Formatted by Jindent --- http://www.jindent.com
